//
// Created by chizuru on 2025/9/29.
//

#include "SensorTPService.h"

SensorTPService::SensorTPService(SensorTPDevice &s, std::shared_ptr<TinyXmlRegisterTPMap> t, RetryPolicy rp)
    : SensorTPController(s, t, rp){
}

OperationResult SensorTPService::checkIfSerialPortIsConnected() {

    return OperationResult();
}

OperationResult SensorTPService::checkIfHasSensorConnected() {
    std::vector<std::optional<uint32_t>> out;
    auto r = getRegisters(dev, {{"ReadOnlyDataSegment", "FeatureCode"}}, out);
    if (!r.success) {
        return r;
    }
    if (static_cast<uint16_t>(*out[0] & 0xffff) != 0x8188) {
        return OperationResult::Fail(ErrorCode::ReadFailure, "No sensor");
    }
    return OperationResult::Ok( "Connected");
}

OperationResult SensorTPService::initSlaveAddress() {
    std::vector<std::optional<uint32_t>> out;
    auto r = getRegisters(dev, {{"UserDataSegment", "DeviceAddress"}}, out);
    if (!r.success) {
        return r;
    }

    dev = static_cast<uint16_t>(*out[0] & 0xffff);
}

OperationResult SensorTPService::batchSetInitRegisters() {
    /* 考虑幂等 */
    std::vector<std::optional<uint32_t>> out;
    std::vector<std::optional<uint32_t>> regDefaultValues{
        0x0001,
        0x00002580,
        0x0000,
        0x0003,
        0x0003,
        0x3f800000,
        0x00000000,
        0x00000000,
        0x0001,
        0x0081
    };
    auto r = getRegisters(dev, {
        {"UserDataSegment", "DeviceAddress"},
        {"UserDataSegment", "BaudRate"},
        {"UserDataSegment", "ParityCheck"},
        {"UserDataSegment", "PressureDecimalPoint"},
        {"UserDataSegment", "TemperatureDecimalPoint"},
        {"UserDataSegment", "PressureGainCoefficient"},
        {"UserDataSegment", "PressureBaseValue"},
        {"UserDataSegment", "TemperatureBaseValue"},
        {"UserDataSegment", "PressureUnit"},
        {"UserDataSegment", "TemperatureUnit"}
    }, out);
    if (!r.success) {
        return r;
    }

    bool ok = regDefaultValues == out;
    if (ok) {
        return OperationResult::Ok();
    }

    r = setRegisters(dev, {
            {"UserDataSegment", "DeviceAddress", 0x0001},
            {"UserDataSegment", "BaudRate", 0x00002580},
            {"UserDataSegment", "ParityCheck", 0x0000},
            {"UserDataSegment", "PressureDecimalPoint", 0x0003},
            {"UserDataSegment", "TemperatureDecimalPoint", 0x0003},
            {"UserDataSegment", "PressureGainCoefficient", 0x3f800000},
            {"UserDataSegment", "PressureBaseValue", 0x00000000},
            {"UserDataSegment", "TemperatureBaseValue", 0x00000000},
            {"UserDataSegment", "PressureUnit", 0x0001},
            {"UserDataSegment", "TemperatureUnit", 0x0081}
    });
    if (!r.success) {
        return r;
    }
    return OperationResult::Ok();
}

OperationResult SensorTPService::getTemperature(float &value) {
    std::vector<std::optional<uint32_t>> out;
    auto r = getRegisters(dev, {{"ReadOnlyDataSegment", "TemperatureValue"}}, out);
    if (!r.success) {
        return r;
    }
    value = *((float*)&*out[0]);
    return OperationResult::Ok();
}

OperationResult SensorTPService::getPressure(float &value) {
    std::vector<std::optional<uint32_t>> out;
    auto r = getRegisters(dev, {{"ReadOnlyDataSegment", "PressureValue"}}, out);
    if (!r.success) {
        return r;
    }
    value = *((float*)&*out[0]);
    return OperationResult::Ok();
}
